package com.zxwl.base.dao;

import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.MappingException;
import org.hibernate.cfg.Configuration;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.Setter;
import org.hibernate.type.AbstractType;
import org.hibernate.type.NullableType;

public class EntityHelper<T>
{
	private Map<String,PropertyInfo> propertys;
	private Set<String> columns;
	private Class<T> entityClass;
	
	public EntityHelper(Class<T> entityClass) throws MappingException, InstantiationException, IllegalAccessException
	{
		this.entityClass = entityClass;
		propertys = new HashMap<String,PropertyInfo>();
		Configuration config = new Configuration().addClass(entityClass);
		PersistentClass pc= config.getClassMapping(entityClass.getName());
		
		Property pid = pc.getIdentifierProperty();
		
		if(null != pid )
		{
			Column column = (Column)pid.getValue().getColumnIterator().next();
			PropertyAccessor par = pid.getPropertyAccessor(entityClass);
			Setter setter = par.getSetter(entityClass, pid.getName());
			if(null != column && null != setter)
			{
				PropertyInfo property = new PropertyInfo();
				property.setColumnName(column.getName());
				property.setPropertyName(pid.getName());
				property.setType(pid.getType());
				// 构建一个类型转换器
				AbstractType type = (AbstractType) pid.getType().getClass().newInstance();
				property.setTypeConverter(type);
				property.setSetter(setter);
				propertys.put(column.getName(), property);
			}
			
		}
		
		@SuppressWarnings("unchecked")
		Iterator<Property> iter = pc.getPropertyIterator();
		for(;iter.hasNext();)
		{
			Property pci = iter.next();
			Column column = (Column)pci.getValue().getColumnIterator().next();
			PropertyAccessor par= pci.getPropertyAccessor(entityClass);
			
			Setter setter = par.getSetter(entityClass, pci.getName());
			if(null != column && null != setter)
			{
				PropertyInfo property = new PropertyInfo();
				property.setColumnName(column.getName());
				property.setPropertyName(pci.getName());
				property.setSetter(setter);
				property.setType(pci.getType());
				AbstractType type = (AbstractType) pci.getType().getClass().newInstance();
				property.setTypeConverter(type);
				propertys.put(column.getName(), property);
			}
		}
		
		this.columns = this.propertys.keySet();
	}
	
	List<T> convert(ResultSet rs) 
			throws SQLException, 
			InstantiationException, 
			IllegalAccessException, 
			IllegalArgumentException, 
			InvocationTargetException
	{
		List<T> list = new ArrayList<T>();
		PropertyInfo  property;
		while (rs.next())
		{
			T entity = entityClass.newInstance();
			for(String column:this.columns)
			{
				property = this.propertys.get(column);
				if(null !=  property)
				{
					try
					{
						property.setValue(entity, ((NullableType) property.getTypeConverter()).get(rs, column));
					}
					catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
			list.add(entity);
		}
		return list;
	}
	
	public PropertyInfo getProperty(String paraName)
	{
		String key;
		key = paraName.substring(0, 1).toUpperCase() + paraName.substring(1);
		
		if(propertys.containsKey(key))
		{
			PropertyInfo property = propertys.get(key);
			if(property != null)
			{
				return property;
			}
		}
		return null;
	}
}
